package com.digdes.calendar.gwt.client.widget;

/**
 * User: Dmitry
 * Date: 01.05.12
 * Time: 8:58
 */

import com.digdes.calendar.gwt.client.dto.EventDTOImpl;
import com.digdes.calendar.gwt.client.dto.PlaceDTOImpl;
import com.digdes.calendar.gwt.client.dto.UserDTOImpl;
import com.digdes.calendar.gwt.client.service.CalendarService;
import com.digdes.calendar.gwt.client.service.CalendarServiceAsync;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.Window;

import java.util.*;

public class Plan extends Composite {
    private String[] timesCell = new String[]{"9-00", "10-00", "11-00", "12-00",
            "13-00", "14-00", "15-00", "16-00", "17-00", "18-00"};
    private int blockcell = timesCell.length - 1;
    public MainPanel panel;
    ChoiceDialog choiceDialog;
    CreateEventDialog createEventDialog;
    private final CalendarServiceAsync calendarservice = GWT.create(CalendarService.class);

    public Plan() {

        panel = new MainPanel();
        choiceDialog = new ChoiceDialog(this);

        drawScheduler(0);

        panel.addUser.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent clickEvent) {
                choiceDialog.showDialog('u');
            }
        });

        panel.addPlace.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent clickEvent) {
                choiceDialog.showDialog('p');
            }
        });

        panel.goEventCreate.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {

                createEventDialog.dateStart.setValue(panel.dateStart.getValue());
                createEventDialog.dateFinish.setValue(panel.dateFinish.getValue());
                createEventDialog.timeStart.setSelectedIndex(panel.timeStart.getSelectedIndex());
                createEventDialog.timeFinish.setSelectedIndex(panel.timeFinish.getSelectedIndex());

                createEventDialog.selectUsers.clear();
                createEventDialog.selectPlace = null;
                for (Object o : choiceDialog.records) {
                    if (o instanceof UserDTOImpl) {
                        createEventDialog.selectUsers.add((UserDTOImpl) o);
                    }
                    // установка места события и проверка на то, что место выбрано одно
                    if (o instanceof PlaceDTOImpl) {
                        if (createEventDialog.selectPlace == null) {
                            createEventDialog.selectPlace = (PlaceDTOImpl) o;
                        } else {
                            Window.alert("У события не может быть 2 места проведения.");
                            return;
                        }
                    }
                }
                RootPanel.get("scheduler").setVisible(false);
                RootPanel.get("main").setVisible(true);
                createEventDialog.showDialog();
            }
        });

        panel.dateStart.addValueChangeHandler(new ValueChangeHandler<Date>() {
            public void onValueChange(ValueChangeEvent<Date> event) {
                if (panel.dateStart.getValue().getTime() - panel.dateFinish.getValue().getTime() > 0) {
                    panel.dateStart.setValue(new Date(panel.dateFinish.getValue().getTime()));
                    Window.alert("Дата начала должна быть раньше даты окончания события.");
                }
                panel.setCountday((int) ((panel.dateFinish.getValue().getTime()
                        - panel.dateStart.getValue().getTime()) / 86400000) + 1);
                panel.setHsize(blockcell * panel.getCountday());
                drawScheduler(0);
            }
        });


        panel.dateFinish.addValueChangeHandler(new ValueChangeHandler<Date>() {

            public void onValueChange(ValueChangeEvent<Date> event) {
                panel.setCountday((int) ((panel.dateFinish.getValue().getTime()
                        - panel.dateStart.getValue().getTime()) / 86400000) + 1);
                panel.setHsize(blockcell * panel.getCountday());
                drawScheduler(0);
            }
        });
        panel.timeStart.addChangeHandler(new ChangeHandler() {
            public void onChange(ChangeEvent changeEvent) {
                drawScheduler(0);
            }
        });
        panel.timeFinish.addChangeHandler(new ChangeHandler() {
            public void onChange(ChangeEvent changeEvent) {
                drawScheduler(0);
            }
        });


        // добавление удаления по клавише delete пользователей и мест
        panel.persons.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent clickEvent) {
                //получение координат выделенной ячейки
                final int cellIndex = panel.persons.getCellForEvent(clickEvent).getCellIndex();
                final int rowIndex = panel.persons.getCellForEvent(clickEvent).getRowIndex();

                if (rowIndex < panel.getCurLine() - 1) {
                    //проверяется не выделена ли была до щелчка та же самая ячейка, создается textbox и помещяется в ячейку
                    // вместо текста ячейки.

                    if (panel.persons.getWidget(rowIndex, cellIndex) == null) {
                        final TextBox textBox = new TextBox();
                        textBox.setReadOnly(true);
                        textBox.setText(panel.persons.getText(rowIndex, cellIndex));

                        // если с ячейки снимается фокус, то ее содержимое снова становится обычным тесктом
                        textBox.addBlurHandler(new BlurHandler() {
                            public void onBlur(BlurEvent blurEvent) {
                                panel.persons.setText(rowIndex, cellIndex, textBox.getText());
                                panel.persons.setText(rowIndex, 0, "");
                            }
                        });
                        Button delButton = new Button();
                        delButton.setStyleName("buttonDeleteRecord");

                        delButton.addMouseDownHandler(new MouseDownHandler() {
                            public void onMouseDown(MouseDownEvent event) {
                                choiceDialog.records.remove(rowIndex);
                                panel.persons.removeRow(rowIndex);
                                panel.schedulerMain.removeRow(rowIndex);
                                panel.setCurLine(panel.getCurLine() - 1);
                                panel.setVsize(panel.getVsize() - 1);
                                if (panel.getVsize() < 20) addLine();
                                drawScheduler(0);
                            }
                        });
                        panel.persons.setWidget(rowIndex, 0, delButton);
                        // настройка удаления по клавище del или backspace.


                        textBox.addKeyPressHandler(new KeyPressHandler() {
                            public void onKeyPress(KeyPressEvent keyPressEvent) {
                                if ((keyPressEvent.getNativeEvent().getKeyCode() == KeyCodes.KEY_DELETE)
                                        || (keyPressEvent.getNativeEvent().getKeyCode() == KeyCodes.KEY_BACKSPACE)) {

                                    choiceDialog.records.remove(rowIndex);
                                    panel.persons.removeRow(rowIndex);
                                    panel.schedulerMain.removeRow(rowIndex);
                                    panel.setCurLine(panel.getCurLine() - 1);
                                    panel.setVsize(panel.getVsize() - 1);
                                    if (panel.getVsize() < 20) addLine();
                                    drawScheduler(0);
                                }
                            }
                        });
                        panel.persons.setWidget(rowIndex, cellIndex, textBox);
                        textBox.setFocus(true);
                    }
                }
            }
        }

        );

        initWidget(panel);

    }

    public void setCreateEventDialog(CreateEventDialog createEventDialog) {
        this.createEventDialog = createEventDialog;
    }

    public void addRecord(Object o, int line) {
        if (o instanceof UserDTOImpl) {
            UserDTOImpl user = (UserDTOImpl) o;
            // формирования строки для отображения участника. Имя и отчество сокращаются.
            StringBuilder personLine = new StringBuilder();
            personLine.append("<div>");
            if (user.getSurname() != null) {
                personLine.append(user.getSurname());
                personLine.append(" ");
            }
            if (user.getName() != null) {
                personLine.append(user.getName().substring(0, 1));
                personLine.append(".");
            }
            if (user.getPatronymic() != null) {
                personLine.append(user.getPatronymic().substring(0, 1));
                personLine.append(".");
            }

            personLine.append("</div>");
            panel.persons.setHTML(line, 1, personLine.toString());
            drawUser(user.getId(), line + 2);
        } else {
            PlaceDTOImpl place = (PlaceDTOImpl) o;
            if (place != null && place.getAddress() != null) {
                StringBuilder personLine = new StringBuilder();
                personLine.append("<div>");
                personLine.append(place.getAddress());
                drawPlace(place.getId(), line + 2);
                personLine.append("</div>");
                panel.persons.setHTML(line, 1, personLine.toString());
            }
        }
    }

    public void drawScheduler(int line) {
        panel.schedulerPanel.clear();
        panel.schedulerPanel.add(panel.schedulerMain);
        panel.schedulerHeader.removeAllRows();
        panel.setCountday((int) ((panel.dateFinish.getValue().getTime()
                - panel.dateStart.getValue().getTime()) / 86400000) + 1);
        panel.setHsize(blockcell * panel.getCountday());
        panel.setCurLine(choiceDialog.records.size() + 1);
        DateTimeFormat dateFormat = DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_LONG);
        DateLabel dlabel = new DateLabel(dateFormat);
        Date d = new Date(panel.dateStart.getValue().getTime());
        dlabel.setValue(d);
        for (int i = 0; i < panel.getHsize(); i++) {
            if (i % blockcell == 0) {
                panel.schedulerHeader.setHTML(0, i, dlabel.toString());
                d.setTime(d.getTime() + 86400000);
                dlabel.setValue(d);
            }
            panel.schedulerHeader.setText(1, i, timesCell[i % blockcell]);
            panel.schedulerHeader.getFlexCellFormatter().setStyleName(0, i, "cell");
            panel.schedulerHeader.getFlexCellFormatter().setStyleName(1, i, "cell");
        }
        panel.schedulerMain.removeAllRows();
        for (int j = 0; j < panel.getHsize(); j++)
            for (int i = 0; i < panel.getVsize(); i++) {
                panel.schedulerMain.getFlexCellFormatter().setStyleName(i, j, "cell");
            }
        panel.persons.removeAllRows();
        for (int i = 0; i < panel.getVsize(); i++) {
            // for (int j = 0; j < 2; j++) {
            panel.persons.getCellFormatter().setStyleName(i, 0, "cellFirst");
            panel.persons.getCellFormatter().setStyleName(i, 1, "cell");
            // }
        }
        for (int i = line; i < choiceDialog.getRecords().size(); i++) {
            Object o = choiceDialog.getRecords().get(i);
            addRecord(o, i);
        }
        panel.refreshTime(0);
        panel.refreshTime(1);
    }

    public void drawPlace(long placeID, int line) {
        final int ii = line;
        Date start = panel.dateStart.getValue();
        start.setTime(start.getTime() + 3600000 * (panel.timeStart.getSelectedIndex() + 9));
        Date finish = panel.dateFinish.getValue();
        finish.setTime(finish.getTime() + 3600000 * (panel.timeFinish.getSelectedIndex() + 9));

        calendarservice.getEventByPlaceAndDate(placeID, start
                , finish, new AsyncCallback<Set<EventDTOImpl>>() {
            public void onFailure(Throwable caught) {
            }

            public void onSuccess(Set<EventDTOImpl> result) {
                panel.schedulerMain.drawLineScheduler(result, ii, panel.dateStart.getValue(), panel.dateFinish.getValue());
            }
        });
    }

    public void drawUser(long userID, int line) {
        final int ii = line;
        // Дополняем к датам события часы, чтобы корректно извлекалось из базы.
        Date start = panel.dateStart.getValue();
        start.setTime(start.getTime() + 3600000 * (panel.timeStart.getSelectedIndex() + 9));
        Date finish = panel.dateFinish.getValue();
        finish.setTime(finish.getTime() + 3600000 * (panel.timeFinish.getSelectedIndex() + 9));
        calendarservice.getEventByUserAndDate(userID, start, finish, new AsyncCallback<Set<EventDTOImpl>>() {
            public void onFailure(Throwable caught) {
            }

            public void onSuccess(Set<EventDTOImpl> result) {
                panel.schedulerMain.drawLineScheduler(result, ii, panel.dateStart.getValue(), panel.dateFinish.getValue());
            }
        });
    }

    public void addLine() {
        panel.setVsize(panel.getVsize() + 1);
        for (int j = 0; j < panel.getHsize(); j++)
            panel.schedulerMain.getFlexCellFormatter().setStyleName(panel.getVsize() - 1, j, "cell");
        panel.schedulerMain.getCellFormatter().addStyleName(panel.getVsize() - 1, panel.timeStart.getSelectedIndex(), "cellGreenLeft");
        int t = blockcell * (panel.getCountday() - 1);
        panel.schedulerMain.getCellFormatter().addStyleName(panel.getVsize() - 1, t + panel.timeFinish.getSelectedIndex(), "cellGreenRight");
        // for (int j = 0; j < 2; j++)
        panel.persons.getCellFormatter().setStyleName(panel.getVsize(), 0, "cellFirst");
        panel.persons.getCellFormatter().setStyleName(panel.getVsize(), 1, "cell");
    }

    public MainPanel getMainPanel() {
        return panel;
    }
}
